/* Microsoft Reference Implementation for TPM 2.0
 *
 *  The copyright in this software is being made available under the BSD License,
 *  included below. This software may be subject to other third party and
 *  contributor rights, including patent rights, and no such rights are granted
 *  under this license.
 *
 *  Copyright (c) Microsoft Corporation
 *
 *  All rights reserved.
 *
 *  BSD License
 *
 *  Redistribution and use in source and binary forms, with or without modification,
 *  are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this list
 *  of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice, this
 *  list of conditions and the following disclaimer in the documentation and/or
 *  other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Tpm.h"
#include "Attest_spt_fp.h"
#include "GetSessionAuditDigest_fp.h"

#if CC_GetSessionAuditDigest  // Conditional expansion of this file

/*(See part 3 specification)
// Get audit session digest
*/
//  Return Type: TPM_RC
//      TPM_RC_KEY          key referenced by 'signHandle' is not a signing key
//      TPM_RC_SCHEME       'inScheme' is incompatible with 'signHandle' type; or
//                          both 'scheme' and key's default scheme are empty; or
//                          'scheme' is empty while key's default scheme requires
//                          explicit input scheme (split signing); or
//                          non-empty default key scheme differs from 'scheme'
//      TPM_RC_TYPE         'sessionHandle' does not reference an audit session
//      TPM_RC_VALUE        digest generated for the given 'scheme' is greater than
//                          the modulus of 'signHandle' (for an RSA key);
//                          invalid commit status or failed to generate "r" value
//                          (for an ECC key)
/*
This command returns a digital signature of the audit session digest.
NOTE 1 See 18.1 for description of how the signing scheme is selected.
If sessionHandle is not an audit session, the TPM shall return TPM_RC_TYPE.
NOTE 2 A session does not become an audit session until the successful completion of the command 
in which the session is first used as an audit session.
This command requires authorization from the privacy administrator of the TPM (expressed with Endorsement Authorization) 
as well as authorization to use the key associated with signHandle.
If this command is audited, then the audit digest that is signed will not include the digest of this command because the 
audit digest is only updated when the command completes successfully.
This command does not cause the audit session to be closed and does not reset the digest value.
NOTE 3 If sessionHandle is used as an audit session for this command, the command is audited in the same manner as any 
other command.
NOTE 4 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL Signature.
此命令返回审计会话摘要的数字签名。
注 1 关于如何选择签名方案的描述见 18.1。
如果 sessionHandle 不是审计会话，TPM 将返回 TPM_RC_TYPE。
注 2：在会话首次用作审核会话的命令成功完成之前，会话不会成为审核会话。
此命令需要 TPM 隐私管理员的授权（用 Endorsement Authorization 表示）以及使用与 signHandle 关联的密钥的授权。
如果审核此命令，则已签名的审核摘要将不包含此命令的摘要，因为审核摘要仅在命令成功完成时更新。
此命令不会导致审计会话关闭，也不会重置摘要值。
注 3 如果 sessionHandle 被用作此命令的审核会话，则该命令将以与任何其他命令相同的方式进行审核。
注 4 如果 signHandle 是 TPM_RH_NULL，则返回 TPMS_ATTEST 结构并且签名是 NULL 签名。

*/
TPM_RC
TPM2_GetSessionAuditDigest(
    GetSessionAuditDigest_In    *in,            // IN: input parameter list
    GetSessionAuditDigest_Out   *out            // OUT: output parameter list
    )
{
    SESSION                 *session = SessionGet(in->sessionHandle);
    TPMS_ATTEST              auditInfo;
    OBJECT                 *signObject = HandleToObject(in->signHandle);
// Input Validation
    if(!IsSigningObject(signObject))
        return TPM_RCS_KEY + RC_GetSessionAuditDigest_signHandle;
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
        return TPM_RCS_SCHEME + RC_GetSessionAuditDigest_inScheme;

    // session must be an audit session
    if(session->attributes.isAudit == CLEAR)
        return TPM_RCS_TYPE + RC_GetSessionAuditDigest_sessionHandle;

// Command Output
    // Fill in attest information common fields
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
                     &auditInfo);

    // SessionAuditDigest specific fields
    auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT;
    auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest;

    // Exclusive audit session
    // TODO: what?
    auditInfo.attested.sessionAudit.exclusiveSession
        = (g_exclusiveAuditSession == in->sessionHandle);

    // Sign attestation structure.  A NULL signature will be returned if
    // signObject is NULL.
    return SignAttestInfo(signObject, &in->inScheme, &auditInfo,
                          &in->qualifyingData, &out->auditInfo,
                          &out->signature);
}

#endif // CC_GetSessionAuditDigest